iOS设计模式 - 代理模式

代理是一种简单而功能强大的设计模式,这种模式用于一个对象“代表”另外一个对象和程序中其他的对象进行交互。 主对象(这里指的是delegating object)中维护一个代理(delegate)的引用并且在合适的时候向这个代理发送消息。这个消息通知“代理”主对象即将处理或是已经处理完了某一个事件。

这个代理可以通过更新自己或是其它对象的UI界面或是其它状态来响应主对象所发送过来的这个事件的消息。或是在某些情况下能返回一个值来影响其它即将发生的事件该如何来处理。

代理的主要价值是它可以让你容易的定制各种对象的行为。注意这里的代理是个名词,它本身是一个对象,这个对象是专门代表被代理对象来和程序中其他对象打交道的。

以上是苹果的官方文档给出的解释,代理模式的应用非常广泛,在系统的 API 中几乎随处可见,代理模式并不是 Swift 或者 Objectvice-C 独有的,它是一种软件设计的思想。代理模式在 WiKiPedia 中的解释如下:

代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式)。

所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网络连接、内存中的大对象、文件或其它昂贵或无法复制的资源。

著名的代理模式例子为引用计数(英语:reference counting)指针对象。

当一个复杂对象的多份副本须存在时,代理模式可以结合享元模式以减少内存用量。典型作法是创建一个复杂对象及多个代理者,每个代理者会引用到原本的复杂对象。而作用在代理者的运算会转送到原本对象。一旦所有的代理者都不存在时,复杂对象会被移除。

如需更详细的解释,请点击这里。如果上面的解释过于晦涩,下面我们将以比较形象的方式,来了解代理这种设计模式。

假设我们有两个对象,ViewController 是一个经销商,Customer 是一个顾客,顾客在要买几件商品,那么该如何告诉经销商呢?下面我们先了解代理模式的原理,再进行实现。

首先我们创建两个类:ViewControllerCustomerCustomer 如果要告诉 ViewController 自己要买多少件,就需要有 ViewController 的一个对象来告诉它,所以我们在 Customer 中创建这个对象:

1
2
3
class Customer: NSObject {
var controller:ViewController!
}

有了这个对象后,我们让 Customer 有买东西的这个行为:

1
2
3
4
5
6
7
8
class Customer: NSObject {
var controller:ViewController!
func buyItemCount (count: NSInteger) {
}
}

当有买的这个行为后,ViewController 还需要有得知 Customer 买东西的方法,因此我们回到 ViewController 中,实现这个方法:

1
2
3
4
5
6
class ViewController: UIViewController {
func customerBuyItemCount(count: NSInteger) {
print("经销商获取到通知 购买\(count)件")
}
}

现在,ViewController 的对象有了,获取通知的方法也有了,那么 Customer 就可以实现买东西这个行为了:

1
2
3
4
5
6
7
8
9
class Customer: NSObject {
var controller:ViewController!
func buyItemCount (count: NSInteger) {
if (self.controller != nil) {
self.controller.customerBuyItemCount(count)
}
}
}

我们回到 ViewController 中,实例化 Customer,实例化 Customer 那边的 ViewController对象Customer 开始买东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let customer = Customer()
customer.controller = self
customer.buyItemCount(5)
}
func customerBuyItemCount(count: NSInteger) {
print("经销商获取到通知 购买\(count)件")
}

现在,我们就通过 ViewController 的对象,获得了 Customer 的购买数量。这也就是代理模式的原理,现在这种方式只能是点对点的进行通信,我们在使用系统 API 时知道,只有实现了代理协议的对象,都可以和被代理的对象进行通信,那么这种功能如何实现呢?

首先我们建立一个代理协议,要求使用这个协议的实现者,必须实现 Customer 买东西的行为:

1
2
3
protocol CustomerDelegate {
func buyItemCount (count: NSInteger , customer:Customer)
}

然后我们声明一个代理对象,用来表示所有需要与 Customer 进行通信的类:

1
2
3
4
5
6
7
8
9
protocol CustomerDelegate {
func buyItemCount (count: NSInteger , customer:Customer)
}
class Customer: NSObject {
var delegate:CustomerDelegate?
}

最后实现代理方法的执行:

1
2
3
4
5
6
7
8
9
func buyItemCountDelegate(count: NSInteger) {
if (self.delegate != nil) && (self.delegate?.buyItemCount != nil) {
print("开始执行代理方法")
self.delegate?.buyItemCount(count, customer: self)
}
}
}

从这里可以看出,实现者必须不为空,并且实现者的代理方法必须存在,这时我们才会执行这个代理方法。

下面,我们回到 ViewController 也就是实现者这里,添加代理协议,并且实现代理方法:

1
2
3
4
5
6
7
8
9
10
class ViewController: UIViewController, CustomerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
func buyItemCount (count: NSInteger , customer:Customer){
print("经销商使用代理方法获取到通知 顾客购买\(count)件")
}

最后,实例化代理对象,并调用代理方法:

1
2
3
4
5
6
7
8
9
10
11
12
class ViewController: UIViewController, CustomerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
customer.delegate = self
customer.buyItemCountDelegate(10)
}
func buyItemCount (count: NSInteger , customer:Customer){
print("经销商使用代理方法获取到通知 顾客购买\(count)件")
}

此时,我们就实现了一个类的代理协议。